/**
 * products - defines the behavior of weather layers, including layer construction, interpolation, and color scales.
 *
 * Copyright (c) 2020 Cameron Beccario
 *
 * For a free version of this project, see https://github.com/cambecc/earth
 */

import {matches as _matches} from "underscore";
import {createPrimaryWavesLayer, createSignificantWaveHeightLayer} from "./ww3/ww3.js";
import {createSSTALayer, createSSTLayer} from "./sst.js";
import {createAuroraLayer} from "./ovation.js";
import {createCurrentsLayer} from "./oscar.js";
import {
    createNO2Layer,
    createPM10Layer,
    createPM1Layer,
    createPM2p5Layer
} from "./cams.js";
import {
    createCO2scLayer,
    createCOSCLayer,
    createDuexttauLayer,
    createSO2SmassLayer,
    createSuexttauLayer,
} from "./geos.js";
import {
    create3HPALayer,
    createAirDensLayer,
    createCAPELayer,
    createMiseryIndexLayer,
    createMSLPLayer,
    createRHLayer,
    createTCWLayer,
    createTempLayer,
    createTPWLayer,
    createWindLayer,
    createWPDLayer,
} from "./gfs/gfs.js";


function matches(...terms) {
    const matchers = terms.map(term => _matches(term));
    return obj => matchers.some(e => e(obj));
}

const FACTORIES = {

    "wind": {
        matchesPrimary: matches({animation_type: "wind"}),
        matchesOverlay: matches({overlay_type: "wind"}),
        create: createWindLayer,
    },

    "temp": {
        matchesOverlay: matches({overlay_type: "temp"}),
        create: createTempLayer,
    },

    "relative_humidity": {
        matchesOverlay: matches({overlay_type: "relative_humidity"}),
        create: createRHLayer,
    },

    "air_density": {
        matchesOverlay: matches({overlay_type: "air_density"}),
        create: createAirDensLayer,
    },

    "wind_power_density": {
        matchesOverlay: matches({overlay_type: "wind_power_density"}),
        create: createWPDLayer,
    },

    "misery_index": {
        matchesOverlay: matches({overlay_type: "misery_index"}),
        create: createMiseryIndexLayer,
    },

    "total_cloud_water": {
        matchesOverlay: matches({overlay_type: "total_cloud_water"}),
        create: createTCWLayer,
    },

    "total_precipitable_water": {
        matchesOverlay: matches({overlay_type: "total_precipitable_water"}),
        create: createTPWLayer,
    },

    "mean_sea_level_pressure": {
        matchesOverlay: matches({overlay_type: "mean_sea_level_pressure"}),
        create: createMSLPLayer,
    },

    "precip_3hr": {
        matchesOverlay: matches({overlay_type: "precip_3hr"}),
        create: create3HPALayer,
    },

    "cape": {
        matchesOverlay: matches({overlay_type: "cape"}),
        create: createCAPELayer,
    },

/*
    "co2": {
        matchesOverlay: matches({overlay_type: "co2"}),
        create: createCO2Layer,
    },
*/

    "cosc": {
        matchesOverlay: matches({overlay_type: "cosc"}),
        create: createCOSCLayer,
    },

    "so2smass": {
        matchesOverlay: matches({overlay_type: "so2smass"}),
        create: createSO2SmassLayer,
    },

    "duexttau": {
        matchesOverlay: matches({overlay_type: "duexttau"}),
        create: createDuexttauLayer,
    },

    "suexttau": {
        matchesOverlay: matches({overlay_type: "suexttau"}),
        create: createSuexttauLayer,
    },

    "co2sc": {
        matchesOverlay: matches({overlay_type: "co2sc"}),
        create: createCO2scLayer,
    },

/*
    "hrrrwind": {
        matchesPrimary: matches({animation_type: "hrrrwind"}),
        matchesOverlay: matches({animation_type: "hrrrwind"}),
        create: createHRRRWindLayer,
    },

    "hrrrtemp": {
        matchesOverlay: matches({overlay_type: "hrrrtemp"}),
        create: createHRRRTempLayer,
    },

    "hrrrradar": {
        matchesOverlay: matches({overlay_type: "hrrrradar"}),
         create: createHRRRRadarLayer,
    },
*/

    "currents": {
        matchesPrimary: matches({animation_type: "currents"}),
        matchesOverlay: matches({overlay_type: "currents"}),
        create: createCurrentsLayer,
    },

    "primary_waves": {
        matchesPrimary: matches({animation_type: "primary_waves"}),
        matchesOverlay: matches({overlay_type: "primary_waves"}),
        create: createPrimaryWavesLayer,
    },

    "significant_wave_height": {
        matchesOverlay: matches({overlay_type: "significant_wave_height"}),
        create: createSignificantWaveHeightLayer,
    },

    "sea_surface_temp": {
        matchesOverlay: matches({overlay_type: "sea_surface_temp"}),
        create: createSSTLayer,
    },

    "sea_surface_temp_anomaly": {
        matchesOverlay: matches({overlay_type: "sea_surface_temp_anomaly"}),
        create: createSSTALayer,
    },

/*
    "argo_mean_temp": {
        matchesOverlay: matches({overlay_type: "argo_mean_temp"}),
        create: createArgoMeanTempLayer,
    },

    "argo_temp_anom": {
        matchesOverlay: matches({overlay_type: "argo_temp_anom"}),
        create: createArgoTempAnomLayer,
    },

    "argo_mean_salinity": {
        matchesOverlay: matches({overlay_type: "argo_mean_salinity"}),
        create: createArgoMeanSalinityLayer,
    },

    "argo_salinity_anom": {
        matchesOverlay: matches({overlay_type: "argo_salinity_anom"}),
        create: createArgoSalinityAnomLayer,
    },
*/

    "aurora": {
        matchesOverlay: matches({overlay_type: "aurora"}),
        create: createAuroraLayer,
    },

    "pm1": {
        matchesOverlay: matches({overlay_type: "pm1"}),
        create: createPM1Layer,
    },

    "pm2.5": {
        matchesOverlay: matches({overlay_type: "pm2.5"}),
        create: createPM2p5Layer,
    },

    "pm10": {
        matchesOverlay: matches({overlay_type: "pm10"}),
        create: createPM10Layer,
    },

    "no2": {
        matchesOverlay: matches({overlay_type: "no2"}),
        create: createNO2Layer,
    },

/*
    "co": {
        matchesOverlay: matches({overlay_type: "co"}),
        create: createCOLayer,
    },

    "o3": {
        matchesOverlay: matches({overlay_type: "o3"}),
        create: createO3Layer,
    },

    "so2": {
        matchesOverlay: matches({overlay_type: "so2"}),
        create: createSO2Layer,
    },
*/

    "none": {
        matchesOverlay: matches({overlay_type: "none"}),
        create: () => undefined,
    }
};

export function productsFor(attr) {
    const factories = Object.values(FACTORIES);
    const primaryFactory = factories.find(e => e.matchesPrimary?.(attr));
    const overlayFactory = factories.find(e => e.matchesOverlay?.(attr) && e !== primaryFactory);
    
    const primary = primaryFactory?.create(attr)
    const overlay = overlayFactory?.create(attr)
    const products = [
        primary,
        overlay,
    ];
    return products
}

export const overlayTypes = new Set(Object.keys(FACTORIES));
